// 工具函数集合
import { createHash, randomBytes } from 'crypto';
import { Context } from 'koa';
import dayjs from 'dayjs';

/**
 * 生成随机字符串
 * @param length 字符串长度
 * @returns 随机字符串
 */
export const generateRandomString = (length: number = 16): string => {
    return randomBytes(Math.ceil(length / 2))
        .toString('hex')
        .slice(0, length);
};

/**
 * 生成哈希值
 * @param data 要哈希的数据
 * @returns 哈希字符串
 */
export const generateHash = (data: string): string => {
    return createHash('sha256').update(data).digest('hex');
};

/**
 * 格式化日期
 * @param date 日期对象或字符串
 * @param format 格式字符串
 * @returns 格式化后的日期字符串
 */
export const formatDate = (date: Date | string, format: string = 'YYYY-MM-DD HH:mm:ss'): string => {
    const d = new Date(date);

    const replacements: Record<string, string> = {
        'YYYY': d.getFullYear().toString(),
        'MM': (d.getMonth() + 1).toString().padStart(2, '0'),
        'DD': d.getDate().toString().padStart(2, '0'),
        'HH': d.getHours().toString().padStart(2, '0'),
        'mm': d.getMinutes().toString().padStart(2, '0'),
        'ss': d.getSeconds().toString().padStart(2, '0'),
    };

    return format.replace(/YYYY|MM|DD|HH|mm|ss/g, match => replacements[match] || match);
};

/**
 * 验证邮箱格式
 * @param email 邮箱地址
 * @returns 是否有效
 */
export const isValidEmail = (email: string): boolean => {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
};

/**
 * 验证手机号格式（中国）
 * @param phone 手机号
 * @returns 是否有效
 */
export const isValidPhone = (phone: string): boolean => {
    const phoneRegex = /^1[3-9]\d{9}$/;
    return phoneRegex.test(phone);
};

/**
 * 深度克隆对象
 * @param obj 要克隆的对象
 * @returns 克隆后的对象
 */
export const deepClone = <T>(obj: T): T => {
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }

    if (obj instanceof Date) {
        return new Date(obj.getTime()) as unknown as T;
    }

    if (obj instanceof Array) {
        return obj.map(item => deepClone(item)) as unknown as T;
    }

    const cloned = {} as T;
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            cloned[key] = deepClone(obj[key]);
        }
    }

    return cloned;
};

/**
 * 防抖函数
 * @param func 要防抖的函数
 * @param delay 延迟时间（毫秒）
 * @returns 防抖后的函数
 */
export const debounce = <T extends (...args: any[]) => any>(
    func: T,
    delay: number
): ((...args: Parameters<T>) => void) => {
    let timeoutId: NodeJS.Timeout;

    return (...args: Parameters<T>) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func.apply(null, args), delay);
    };
};

/**
 * 节流函数
 * @param func 要节流的函数
 * @param delay 延迟时间（毫秒）
 * @returns 节流后的函数
 */
export const throttle = <T extends (...args: any[]) => any>(
    func: T,
    delay: number
): ((...args: Parameters<T>) => void) => {
    let lastCall = 0;

    return (...args: Parameters<T>) => {
        const now = Date.now();
        if (now - lastCall >= delay) {
            lastCall = now;
            func.apply(null, args);
        }
    };
};

/**
 * 生成分页参数
 * @param page 页码
 * @param pageSize 每页大小
 * @returns 分页参数对象
 */
export const generatePagination = (page: number = 1, pageSize: number = 10) => {
    const skip = (page - 1) * pageSize;
    const limit = pageSize;

    return { skip, limit, page, pageSize };
};

/**
 * 生成响应数据格式
 * @param data 数据
 * @param message 消息
 * @param success 是否成功
 * @returns 响应对象
 */
export const generateResponse = <T>(
    ctx: Context,
    data: T,
    message: string = '操作成功',
) => (ctx.body =
{
    message,
    data,
    code: 200,
    timestamp: dayjs().format('YYYY年MM月DD日 HH:mm:ss'),
});

/**
 * 生成错误响应
 * @param message 错误消息
 * @param code 错误码
 * @returns 错误响应对象
 */
export const generateErrorResponse = (
    ctx: Context,
    message: string = '操作失败',
    code: number = 201,
    details?: any
) => (
    ctx.body =
    {
        message,
        code,
        timestamp: dayjs().format('YYYY年MM月DD日 HH:mm:ss'),
        details,
    });